/*
 * @Author: xiaohao
 * @Date: 2025-10-30 07:03:10
 * @LastEditors: xiaohao
 * @LastEditTime: 2025-11-05 21:39:05
 * @FilePath: /Project/ConcurrentMemoryPool/include/ConcurrentMemoryPool/ObjectPool.h
 * @Description:
 */
#pragma once
#include "Common.h"

// 定长内存池
// template <size_t N>
// class ObjectPool
//{
//
//};

/**
 * @brief 定长对象内存池
 * @tparam T 要管理的对象类型
 */
template <class T>
class ObjectPool
{
public:
    /**
     * @brief 分配一个T类型的对象
     * @return T* 指向新分配对象的指针
     */
    T *New()
    {
        T *obj = nullptr; // 指向新分配的对象

        // 第一步：优先使用自由链表中已回收的内存（复用内存，减少malloc次数）
        if (_freeList != nullptr)
        {
            // 自由链表的节点用自身前4/8字节（指针大小）存储下一个节点地址
            void *next = *(void **)_freeList; // 获取当前空闲节点的下一个节点
            obj = (T *)_freeList;             // 取出当前空闲节点作为新对象
            _freeList = next;                 // 自由链表头指针后移
        }
        else
        {
            // 第二步：自由链表为空，需要从大块内存中切割
            // 如果剩余内存不够分配一个T对象，重新申请一块大块内存（128KB）
            if (_remainBytes < sizeof(T))
            {
                // _memory = (char *)malloc(128 * 1024); // 申请一块128KB的内存
                // if (_memory == nullptr)
                // {
                //     throw std::bad_alloc();
                // }

                size_t kpage = (128 * 1024) / PAGE_SIZE;
                char *newBlock = (char *)SystemAlloc(kpage);
                if (newBlock == MAP_FAILED) // mmap 失败返回 MAP_FAILED（而非 nullptr）
                {
                    throw std::bad_alloc();
                }

                _blocks.push_back(newBlock); // 记录所有 mmap 分配的起始地址
                _memory = newBlock;
                _remainBytes = 128 * 1024;
            }

            // 分配一个T对象
            obj = (T *)_memory;
            size_t objSize = sizeof(T) < sizeof(void *) ? sizeof(void *) : sizeof(T);
            _memory += objSize;
            _remainBytes -= objSize;
        }

        // 定位new, 显示调用T的构造函数的初始化
        new (obj) T;
        return obj;
    }

    /**
     * @brief 释放一个对象
     * @param obj 要释放的对象指针
     */
    void Delete(T *obj)
    {
        if (obj == nullptr)
        {
            return;
        }

        // 显示调用析构函数清理对象
        obj->~T();

        // 将对象链接到自由链表（头插法）
        // 把obj的前指针大小字节作为next指针，指向原来的_freeList
        *(void **)obj = _freeList;
        _freeList = obj;
    }

    // 注意：mmap 分配的内存需要用 munmap 释放，这里增加析构函数
    ~ObjectPool()
    {
        // 释放所有通过 mmap 分配的大块内存（这里简化处理，实际可能需要记录所有 mmap 地址）
        // 释放所有 mmap 分配的大块内存

        // 释放所有通过SystemAlloc申请的内存块
        size_t kpage = (128 * 1024) / PAGE_SIZE;

        for (char *block : _blocks)
        {
            SystemFree(block, kpage);
        }
    }

private:
    std::vector<char *> _blocks; // 记录所有mmap分配的内存块地址
    char *_memory = nullptr;     // 当前大块内存的指针
    size_t _remainBytes = 0;     // 当前大块内存剩余字节数
    void *_freeList = nullptr;   // 自由链表头指针
};